using System.Collections.Concurrent;

namespace Vin.Tool.AspNetCore.Factory;

public class VinKeyedServiceFactory
{
    private class KeyedService
    {
        public string Key { get; set; } = null!;

        public Type ServiceType { get; set; } = null!;
    }

    private static ConcurrentDictionary<Type, List<KeyedService>> KeyedServices { get; } = new();

    public static bool AddKeyedService(string? key, Type serviceType, Type implementationType)
    {
        if (!KeyedServices.ContainsKey(serviceType))
        {
            KeyedServices[serviceType] = new List<KeyedService>();
        }

        // if (KeyedServices[implementationType].Any(m => m.Key == key))
        // {
        //     return false;
        // }

        KeyedServices[serviceType].Add(new KeyedService
        {
            Key = key ?? string.Empty,
            ServiceType = implementationType
        });

        return true;
    }

    public static object? GetKeyedService(IServiceProvider serviceProvider, string? key, Type serviceType)
    {
        key ??= string.Empty;
        if (!KeyedServices.ContainsKey(serviceType))
        {
            return null;
        }

        var type = KeyedServices[serviceType].Find(m => m.Key == key);
        if (type == null)
        {
            return null;
        }

        return serviceProvider.GetService(type.ServiceType);
    }

    public static List<object?> GetKeyedServices(IServiceProvider serviceProvider, string? key, Type serviceType)
    {
        if (!KeyedServices.ContainsKey(serviceType))
        {
            return new List<object?>();
        }

        return KeyedServices[serviceType].Where(m => m.Key == key)
            .Select(m => serviceProvider.GetService(m.ServiceType))
            .ToList();
    }
}